﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
using RH.Common.Extensions;
using RH.Domain;
using RH.Web.ViewModels;
using RH.Web.Utility;
using RH.Web.ViewModels.UtilityModels;
using AutoMapper;

namespace RH.Web.Areas.Admin.Controllers
{
	[Authorize(Roles="Admin")]
    public class ServicePeriodController : BaseController
    {
		private AppEntities _Context = null;
		private EntityRepository _Repository = null;
        
		#region Constructors
		public ServicePeriodController()
		{
			_Context = new AppEntities();
			_Repository = new EntityRepository(_Context);
		}

		public ServicePeriodController(UserViewModel currentUser)
			: base(currentUser)
        {
			_Context = new AppEntities();
			_Repository = new EntityRepository(_Context);
        }
		#endregion Constructors

		#region Action Methods
        //public ActionResult Index()
        //{
        //    return View("List", BuildServicePeriodListConfig(0));
        //}

		public ActionResult List()
        {
            
            //return View(BuildServicePeriodListConfig(1));
            return View();
        }

		/// <summary>
        /// Gets a ServicePeriod from Database to edit
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
		public ActionResult Edit(int id = 0, int companyId = 0, String IsSaved = null)
        {
            ServicePeriod entity = null;
            if (id == 0 && companyId > 0)
            {
                entity = new ServicePeriod();
                entity.CompanyID = companyId;
            }
            else
                entity = _Context.ServicePeriods.FirstOrDefault(P => P.ID == id && P.CompanyID == companyId);

            ServicePeriodViewModel viewModel = Mapper.Map<ServicePeriod, ServicePeriodViewModel>(entity);
            
            if (String.Compare(IsSaved, "true", true) == 0)
                ViewData[AppConstants.ViewDataKeys.SAVED] = true;
			return View(viewModel);
        }

		/// <summary>
        /// Saves ServicePeriod Information into the Database
        /// </summary>
        /// <param name="viewModel"></param>
        /// <returns></returns>
		[HttpPost]
		public ActionResult Edit(ServicePeriodViewModel viewModel)
        {
            if (!ModelState.IsValid)
                return View(viewModel);
            else
            {
                String message = IsOverlappingServicePeriod(viewModel);
                if (!message.IsNullOrEmpty())
                {
                    ModelState.AddModelError("DuplicateServicePeriod", message);
                    return View(viewModel);
                }
            }

			ServicePeriod entity = null; 
			if (viewModel.ID == 0)
            {
                entity = new ServicePeriod();
                entity.CreatedOn = DateTime.Now;
                entity.IsActive = true ;
                _Context.AddToServicePeriods(entity);
            }
            else
                entity = _Context.ServicePeriods.FirstOrDefault(P => P.ID == viewModel.ID);

            entity = Mapper.Map<ServicePeriodViewModel, ServicePeriod>(viewModel, entity);
            
            CreateSpan(entity, viewModel.LeadPerSpan);
		
            _Context.SaveChanges();
            //return RedirectToAction("Index");
			return RedirectToAction(String.Format("Edit/{0}", entity.ID), new { CompanyID = viewModel.CompanyID, IsSaved = "true" });
        }
        
        /// <summary>
        /// Edits a Service Period Span
        /// </summary>
        /// <param name="id"></param>
        /// <param name="IsSaved"></param>
        /// <returns></returns>
        public ActionResult EditSpan(int id = 0, String IsSaved = null)
        {
            ServicePeriodSpan entity = _Context.ServicePeriodSpans.FirstOrDefault(P => P.ID == id);
            ServicePeriodSpanViewModel viewModel = Mapper.Map<ServicePeriodSpan, ServicePeriodSpanViewModel>(entity);

            if (String.Compare(IsSaved, "true", true) == 0)
                ViewData[AppConstants.ViewDataKeys.SAVED] = true;
            return View(viewModel);
        }

        /// <summary>
        /// Edits a Service Span Period. 
        /// Note: No Service Span can be inserted from user input, users can edit only Committed Lead count per span
        /// </summary>
        /// <param name="viewModel"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult EditSpan(ServicePeriodSpanViewModel viewModel)
        {
            if (!ModelState.IsValid)
                return View(viewModel);

            ServicePeriodSpan entity = _Context.ServicePeriodSpans.FirstOrDefault(P => P.ID == viewModel.ID);
            entity.LeadPerSpan = viewModel.LeadPerSpan;
            _Context.SaveChanges();
            return RedirectToAction(String.Format("EditSpan/{0}", entity.ID), new { IsSaved = "true" });
        }

        private String IsOverlappingServicePeriod(ServicePeriodViewModel viewModel)
        {
            DateTime startDate = viewModel.StartDate.ToDateTime(ConfigReader.CSharpCalendarDateFormat);
            DateTime endDate = startDate.AddDays((viewModel.TotalSpan * viewModel.SpanDuration) + viewModel.TotalSpan);
            int companyID = viewModel.CompanyID.ToInt();
            var servicePeriod = _Context.ServicePeriodSpans.FirstOrDefault( P => P.ServicePeriod.CompanyID == companyID && P.StartDate >= startDate && P.EndDate <= endDate && !P.IsDeleted);

            if (servicePeriod == null)
                return String.Empty;
            else
                return String.Format("Overlapping Service Period found within this date range, strating from {0} To {1}", 
                    servicePeriod.StartDate.ToString(ConfigReader.CSharpCalendarDateFormat),
                    servicePeriod.EndDate.ToString(ConfigReader.CSharpCalendarDateFormat));
        }

        private void CreateSpan(ServicePeriod entity, int leadPerSpan)
        {
            DateTime endDate = entity.StartDate;
            for (int i = 0; i < entity.TotalSpan; i++)
            {
                ServicePeriodSpan span = new ServicePeriodSpan();
                //span.ServicePeriodID = entity.ID;
                span.StartDate = endDate;
                span.EndDate = endDate.AddDays(entity.SpanDuration);
                span.LeadPerSpan = leadPerSpan;
                endDate = span.EndDate.AddDays(1);
                entity.ServicePeriodSpans.Add(span);
            }
        }

        [HttpPost]
        public PartialViewResult SpanList(int companyID)
        {
            UtilityDAO dao = new UtilityDAO();
            RH.Domain.DbParameter[] parameters = new[]{
                new RH.Domain.DbParameter("@CompanyID", companyID)
            };
            DataSet ds = dao.GetDataSet(DbObject.SP.GET_SERVICEPERIOD_SPANS_BY_COMPANY, parameters, true);
            ListConfig listConfig = new ListConfig(ds.Tables[0], null);
            
            return PartialView("_ServicePeriodSpanList", listConfig);
        }

        /// <summary>
        /// Deletes a Service Period Span (Actually marks as delete)
        /// </summary>
        /// <param name="id"></param>
        /// <returns>
        /// Returns 
        ///     -1 if the specified object does found for delete
        ///     +1 if the specfied object marked successfully for delete
        /// </returns>
        [HttpPost]
        public int DeleteSpan(int id)
        {
            var span = _Context.ServicePeriodSpans.FirstOrDefault(P => P.ID == id);
            if (span == null)
                return -1;
            span.IsDeleted = true;
            //_Context.ServicePeriodSpans.DeleteObject(span);
            _Context.SaveChanges();
            return 1;
        }
		#endregion Action Methods
		
		#region Helper Methods

		/// <summary>
        /// Builds a ListConfig object with a list of ServicePeriod
        /// </summary>
        /// <returns></returns>
		private ListConfig BuildServicePeriodListConfig(int companyID)
		{
			UtilityDAO dao = new UtilityDAO();
            RH.Domain.DbParameter[] parameters = new[]{
                new RH.Domain.DbParameter("@CompanyID", companyID)
            };
            DataSet ds = dao.GetDataSet(DbObject.SP.GET_SERVICEPERIOD_SPANS_BY_COMPANY, parameters, true);
            ListConfig listConfig = new ListConfig(ds.Tables[0], null);
            return listConfig;
		}

        #endregion			
    }
}


